<?php
namespace Siulung\JWT;

class JWTAuth
{
    public $header = [
        'typ' => 'JWT',
        'alg' => 'HS256'
    ];

    public $config = [];

    private $secret = 'RFEv4iQ4uqpHqfer1YGyleV6HDA7t5vXmBIVpHifhhwQGvhZYawIHtfHDLbSQqnI';

    public function __contract(Array $config = [])
    {
        $this->config = $config;
        if (! empty($config['secret'])) {
            $this->secret = $config['secret'];
        }
    }

    public function createToken(Array $payloadArr)
    {
        $header = json_encode($this->header);
        $payload = json_encode($payloadArr);
        $encodeStr = base64_encode($header) . '.' . base64_encode($payload);
        $signature = $this->createSignature($encodeStr);
        $token = $encodeStr . '.' . $signature;
        return json_encode([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => 7200 //单位：s
        ]);
    }

    public function getToken()
    {
        $auth = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
        if (empty($auth)) {
            $token = $_POST['token'] ?? $_GET['token'] ?? '';
        } else {
            $token = substr($auth, 7); //过滤开头的'Bearer '
        }
        return $token;
    }

    public function check()
    {
        return $this->verify($this->getToken());
    }

    public function verify($token)
    {
        try {
            $arr = explode('.', $token);
            if (count($arr) < 3) {
                throw new \Exception('token formal error');
            }
            $header = $arr[0];
            $payload = $arr[1];
            $inputSign = $arr[2];
            $encodeStr = $header . '.' . $payload;
            $signature = $this->createSignature($encodeStr);
            $bool = $signature == $inputSign;
            if ($bool) {
                return $bool;
            } else {
                throw new \Exception('token verify failed');
            }
        } catch (\Exception $e) {
            http_response_code(401);
            exit($e->getMessage());
        }
        
    }

    public function validate(Array $payload)
    {

    }

    private function createSignature($encodeStr)
    {
        $str = $encodeStr . '.' . $this->secret;
        return hash('sha256', $str);
    }

    public function getPayload()
    {
        $token = $this->getToken();
        $payload = $this->parseToken($token)['payload'];
        return json_decode(base64_decode($payload));
    }

    private function parseToken($token)
    {
        try {
            $arr = explode('.', $token);
            if (count($arr) < 3) {
                throw new \Exception('token formal error');
            }
            $header = $arr[0];
            $payload = $arr[1];
            $inputSign = $arr[2];
            return [
                'header' => $header,
                'payload' => $payload,
                'signature' => $inputSign
            ];
        } catch (\Exception $e) {
            http_response_code(401);
            exit($e->getMessage());
        }
    }

    public function refresh()
    {

    }

}